
import 'package:flutter/material.dart';

class PainterBox extends CustomPainter{

  /// 定义了如何绘制这个矩形，例如颜色和样式等。
  final Paint _bgPainter = Paint()
    ..color = Colors.grey.withOpacity(0.2);
  final Paint _mainPainter = Paint()
    ..color = Colors.blue;

  /// 小球半径
  final double _mainCircleRadius = 10;

  @override
  void paint(Canvas canvas, Size size) {
    print("画板大小：${size}");

    // Offset.zero & size: 这是定义Rect对象的一种方式。
    // &运算符在此处用来结合偏移（Offset）和尺寸（Size）来创建一个矩形。
    // Offset.zero表示矩形的左上角从坐标原点（0,0）开始。
    // size参数则定义了这个矩形的高度和宽度。
    canvas.drawRect(Offset.zero & size, _bgPainter);

    //*************** 设置Y轴向上 start ***************
    // 将原点移动到这个位置 - 从这开始绘制的图形，都会根据这个新的原点来设置位置（初始是[0, 0]）
    canvas.translate(0, size.height);
    // 绘制坐标轴
    _drawAxis(canvas, size);
    // canvas.scale(sx, sy)是Canvas类的一个方法，它用来缩放画布。
    // 这个方法接受两个参数，sx和sy，分别表示水平方向和垂直方向的缩放比例。
    // sx参数为1，表示画布在水平方向的原尺寸不变，sy参数为-1，表示画布在垂直方向上进行了翻转。
    canvas.scale(1, -1);
    //*************** 设置Y轴向上 end ***************

    // 绘制小球
    canvas.drawCircle(Offset.zero, _mainCircleRadius, _mainPainter);
    canvas.drawCircle(Offset(100, 100), _mainCircleRadius, _mainPainter);
    canvas.drawCircle(Offset(150, 250), _mainCircleRadius, _mainPainter);
    canvas.drawCircle(Offset(250, 250), _mainCircleRadius, _mainPainter);
    canvas.drawCircle(Offset(50, 150), _mainCircleRadius, _mainPainter);
  }

  /// 这个重写的方法决定当接收到一个新的CustomPainter后，是否需要重绘。
  /// 在你的代码中，shouldRepaint返回false，表示不需要重绘。
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }

  /// 坐标轴画笔
  final Paint _axisPaint = Paint()
    ..color = Colors.black
    // PaintingStyle是一个枚举，有两个值，fill和stroke。
    // fill表示填充，stroke表示描边
    ..style = PaintingStyle.stroke
    // 设定了画笔的宽度为1
    ..strokeWidth = 1;

  /// 坐标轴文字的画笔
  final TextPainter textPainter = TextPainter(
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr
  );

  /// 创建坐标轴
  void _drawAxis(Canvas canvas, Size size) {
    // 绘制轴
    Path axisPath = Path();
    // 绘制x轴 - relativeLineTo 画个线段 - 从原点到参数中的位置画个线段
    axisPath.relativeLineTo(size.width, 0);
    axisPath.relativeLineTo(-10, -4); // 画箭头的下半部分
    axisPath.moveTo(size.width, 0); // 将画笔的y回到轴上，要不然就是接着画了成一个倒三角了
    axisPath.relativeLineTo(-10, 4); // 画箭头的上半部分

    // 回归到原点 - 准备画Y轴
    axisPath.moveTo(0, 0);

    // 绘制Y轴
    axisPath.relativeLineTo(0, -size.height);
    axisPath.relativeLineTo(-4, 10);
    axisPath.moveTo(0, -size.height);
    axisPath.relativeLineTo(4, 10);
    canvas.drawPath(axisPath, _axisPaint);


    // 开始绘制轴名称
    textPainter.text = const TextSpan(
      text: "x 轴",
      style: TextStyle(fontSize: 12, color: Colors.blue)
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(size.width - textPainter.size.width, 5));

    textPainter.text = const TextSpan(
      text: "y 轴",
      style: TextStyle(fontSize: 18, color: Colors.red)
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(-textPainter.size.width - 5, -size.height));

  }

}